package com.atguigu.yygh.order.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.atguigu.yygh.enums.PaymentTypeEnum;
import com.atguigu.yygh.enums.RefundStatusEnum;
import com.atguigu.yygh.model.order.OrderInfo;
import com.atguigu.yygh.model.order.PaymentInfo;
import com.atguigu.yygh.model.order.RefundInfo;
import com.atguigu.yygh.order.service.OrderService;
import com.atguigu.yygh.order.service.PaymentService;
import com.atguigu.yygh.order.service.RefundInfoService;
import com.atguigu.yygh.order.service.WeixinService;
import com.atguigu.yygh.order.utils.ConstantPropertiesUtils;
import com.atguigu.yygh.order.utils.HttpClient;
import com.github.wxpay.sdk.WXPayUtil;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author 杨林
 * @create 2022-11-18 21:20 星期五
 * description:
 */
@Service
public class WeixinServiceImpl implements WeixinService {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private PaymentService paymentService;

    @Autowired
    private OrderService orderService;

    /**
     * 根据订单号下单 生成支付链接
     * @param orderId
     * @return
     */
    @Override
    public Map createNative(Long orderId) {

        //检查redis中是否存在该订单的支付链接
        Map map = (Map)redisTemplate.boundValueOps(orderId.toString()).get();
        if (map != null){ //说明redis中存在该订单的支付链接
            return map;
        }

        //根据id获取订单信息
        OrderInfo order = orderService.getOrderInfo(orderId);

        //保存交易记录 （一个订单只能有一个交易记录）
        //表明支付方式为微信
        paymentService.saveOrderInfo(order, PaymentTypeEnum.WEIXIN.getStatus());

        //调用微信统一下单接口 （封装参数）
        Map<String,String> payMap = new HashMap();
        payMap.put("appid", ConstantPropertiesUtils.APPID); //公众账号ID
        payMap.put("mch_id",ConstantPropertiesUtils.PARTNER); //商户号
        payMap.put("nonce_str", WXPayUtil.generateNonceStr()); //随机字符串  32位
        //payMap.put("sign", );
        Date reserveDate = order.getReserveDate();  //安排日期
        String reserveDateString = new DateTime(reserveDate).toString("yyyy-MM-dd");
        String body = reserveDateString + "就诊"+ order.getDepname();
        payMap.put("body", body);
        payMap.put("out_trade_no", order.getOutTradeNo());
        //payMap.put("total_fee", order.getAmount().multiply(new BigDecimal("100")).longValue()+""); //支付金额 （单位：分）
        payMap.put("total_fee", "1");
        payMap.put("spbill_create_ip", "127.0.0.1");
        payMap.put("notify_url","http://guli.shop/api/order/weixinPay/weixinNotify");
        payMap.put("trade_type","NATIVE");

        try {
            //使用HttpClient调用统一下单接口
            HttpClient client = new HttpClient("https://api.mch.weixin.qq.com/pay/unifiedorder");
            //String s = WXPayUtil.generateSignedXml(payMap, ConstantPropertiesUtils.PARTNERKEY);
            client.setHttps(true);
            client.setXmlParam(WXPayUtil.generateSignedXml(payMap, ConstantPropertiesUtils.PARTNERKEY));//xml格式的字符串参数
            client.post();

            //解析微信端的返回值
            String content = client.getContent();
            Map<String, String> contentMap = WXPayUtil.xmlToMap(content);

            //封装结果
            Map<String,Object> result = new HashMap<>();
            result.put("orderId", orderId);
            result.put("codeUrl", contentMap.get("code_url"));
            result.put("totalFee", order.getAmount());
            result.put("resultCode", contentMap.get("result_code"));

            //将结果暂存在redis中5分钟
            redisTemplate.boundValueOps(orderId + "").set(result, 5, TimeUnit.MINUTES);

            return result;

        } catch (Exception e) {
            e.printStackTrace();
        }

        return null; //支付链接在map中
    }


    /**
     * 查询订单支付状态   （调用微信端接口）
     * @param orderId
     * @return
     */
    @Override
    public Map queryPayStatus(Long orderId) {

        //1.查询订单
        OrderInfo orderInfo = orderService.getById(orderId);

        //2.封装参数
        Map<String,String> map = new HashMap<>();
        map.put("appid",ConstantPropertiesUtils.APPID);
        map.put("mch_id",ConstantPropertiesUtils.PARTNER);
        map.put("out_trade_no",orderInfo.getOutTradeNo());
        map.put("nonce_str",WXPayUtil.generateNonceStr());
        //paramMap.put("sign", );


        try {
            //3.调用微信端查询支付状态接口
            String s = WXPayUtil.generateSignedXml(map, ConstantPropertiesUtils.PARTNERKEY);
            HttpClient client = new HttpClient("https://api.mch.weixin.qq.com/pay/orderquery");
            client.setHttps(true);
            client.setXmlParam(s);
            client.post();

            //4.微信端返回值转成map
            String content = client.getContent();
            Map<String, String> resultMap = WXPayUtil.xmlToMap(content);

            //5.返回结果
            return resultMap;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;


        //1、根据订单id查询订单，为了获取到outTradeNo
//        OrderInfo orderInfo = orderService.getById(orderId);
//
//
//        //2、封装参数
//        Map<String,String> map = new HashMap<>();
//        map.put("appid",ConstantPropertiesUtils.APPID);
//        map.put("mch_id",ConstantPropertiesUtils.PARTNER);
//        map.put("out_trade_no",orderInfo.getOutTradeNo());
//        map.put("nonce_str",WXPayUtil.generateNonceStr());
//
//        try {
//            //3、map转成xml格式的字符串，并且自动添加sign签名
//            String s = WXPayUtil.generateSignedXml(map, ConstantPropertiesUtils.PARTNERKEY);
//
//            //4、发请求（查询订单状态）
//            String url = "https://api.mch.weixin.qq.com/pay/orderquery";
//            HttpClient httpClient = new HttpClient(url);
//            httpClient.setHttps(true);
//            httpClient.setXmlParam(s);
//            httpClient.post();
//
//            //5、微信端返回值
//            String content = httpClient.getContent();
//            Map<String, String> resultMap = WXPayUtil.xmlToMap(content);
//
//            return resultMap;
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//
//        return null;
    }


    @Autowired
    private RefundInfoService refundInfoService;

    /**
     * 是否完成退款
     * @param orderId
     * @return
     */
    @Override
    public Boolean refund(Long orderId) {

        //查询支付记录
        //PaymentTypeEnum.WEIXIN.getStatus()  2  表示微信支付
        PaymentInfo paymentInfo = paymentService.getPaymentInfo(orderId, PaymentTypeEnum.WEIXIN.getStatus());

        //根据支付记录创建退款记录
        RefundInfo refundInfo = refundInfoService.saveRefundInfo(paymentInfo);

        //判断退款状态 是否已经完成退款
        Integer refundStatus = refundInfo.getRefundStatus();  //当前退款记录的退款状态

        //表示退款已经完成 返回 true
        if (refundStatus.equals(RefundStatusEnum.REFUND.getStatus())){
            return true;
        }

        //封装退款参数
        Map<String,String> map = new HashMap<>();
        map.put("appid", ConstantPropertiesUtils.APPID);  //公众账号id
        map.put("mch_id", ConstantPropertiesUtils.PARTNER);  //商户编号
        map.put("nonce_str",WXPayUtil.generateNonceStr());  //随机字符串
        map.put("transaction_id", paymentInfo.getTradeNo());  //微信订单号
        map.put("out_trade_no", paymentInfo.getOutTradeNo()); //商品订单编号
        map.put("out_refund_no", "tk" + paymentInfo.getOutTradeNo());  //商品退款单号
        //total_fee   refund_fee   均为测试数据    单位为分
        map.put("total_fee", "1");  //订单金额
        map.put("refund_fee", "1");  //退款金额

//        //4、封装退款参数
//        Map<String,String> paramMap = new HashMap<>();
//        paramMap.put("appid",ConstantPropertiesUtils.APPID); //公众账号ID
//        paramMap.put("mch_id",ConstantPropertiesUtils.PARTNER); //商户编号
//        paramMap.put("nonce_str",WXPayUtil.generateNonceStr()); //随机字符串
//        paramMap.put("transaction_id",paymentInfo.getTradeNo()); //微信订单号
//        paramMap.put("out_trade_no",paymentInfo.getOutTradeNo()); //商户订单编号
//        paramMap.put("out_refund_no","tk"+paymentInfo.getOutTradeNo()); //商户退款单号
//        paramMap.put("total_fee","1");//订单金额
//        paramMap.put("refund_fee","1");//退款金额

        //调用微信退款接口
        try {
            //将 map 转换为xml格式的字符串
            String s = WXPayUtil.generateSignedXml(map, ConstantPropertiesUtils.PARTNERKEY);

            //调用微信接口
            HttpClient client = new HttpClient("https://api.mch.weixin.qq.com/secapi/pay/refund");
            client.setHttps(true);
            client.setXmlParam(s);
            client.setCert(true);
            client.setCertPassword(ConstantPropertiesUtils.PARTNER);
            client.post();

            //5、调用微信退款接口
//            String paramXml = WXPayUtil.generateSignedXml(paramMap,ConstantPropertiesUtils.PARTNERKEY);
//            HttpClient client = new HttpClient("https://api.mch.weixin.qq.com/secapi/pay/refund");
//
//            client.setXmlParam(paramXml);
//            client.setHttps(true);
//            client.setCert(true);
//            client.setCertPassword(ConstantPropertiesUtils.PARTNER);
//            client.post();

            //接收微信端返回参数
            String content = client.getContent();
            //将微信端返回的xml格式的数据转换为map
            Map<String, String> resultMap = WXPayUtil.xmlToMap(content);

            //更新退款记录状态
            if (resultMap != null  && "SUCCESS".equals(resultMap.get("result_code"))){
                //退款单号  （由微信端返回）
                refundInfo.setTradeNo(resultMap.get("refund_id"));
                //退款状态
                refundInfo.setRefundStatus(RefundStatusEnum.REFUND.getStatus());
                refundInfo.setCallbackTime(new Date());
                //将返回的参数转换成字符串保存
                refundInfo.setCallbackContent(JSONObject.toJSONString(resultMap));
                refundInfoService.updateById(refundInfo);
            }

        } catch (Exception e) {
            return false;
        }
        return true;
    }
}
